home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS / lang / C / decl.g next >
Encoding:
Text File  |  1994-09-14  |  14.0 KB  |  569 lines  |  [TEXT/MPS ]

  1. /*
  2.  * ANSI C recognizer
  3.  *
  4.  * Gives some error messages for semantics, but this grammar
  5.  * checks mostly syntax.  We make no claim that it rigorously follows
  6.  * the ANSI C standard, but it's a good start.
  7.  *
  8.  * Type trees are constructed and maintained in the symbol table.
  9.  * Expression trees are constructed and then thrown away.  The
  10.  * user can presumably do something more useful with them.
  11.  *
  12.  * Requires PCCTS Version 1.00
  13.  *
  14.  * Terence Parr
  15.  * July 1991
  16.  */
  17.  
  18. #header <<
  19.     #define D_TextSize 20
  20.     #include "charbuf.h"
  21.     #include "type.h"
  22.     #include "sym.h"
  23.     #include "proto.h"
  24.     #include <string.h>
  25. >>
  26.  
  27. #parser "C"
  28.  
  29. #token "[\ \t]+"    << zzskip(); >>
  30. #token "\n"            << zzline++; zzskip(); >>
  31.  
  32. #token "#line [\ \t]+ [0-9]+ ~[\n]*\n"
  33.                     << zzline = atoi(zzlextext+5); zzskip(); >>
  34. #token "# [\ \t]+ [0-9]+ ~[\n]*\n"
  35.                     << zzline = atoi(zzlextext+1); zzskip(); >>
  36.  
  37. #token "\""            << zzmode(STRINGS); zzmore(); >>
  38. #token "'"            << zzmode(CHARACTERS); zzmore(); >>
  39.  
  40. /* these tokens are used as node types, but not referenced in grammar */
  41. #token Var
  42. #token Func
  43. #token FuncCall
  44. #token Label
  45. #token PostInc
  46. #token PostDec
  47. #token StructPtrRef
  48. #token StructRef
  49. #token AggrTag
  50.  
  51. #lexclass STRINGS
  52. #token STRING "\""    << zzmode(START); >>
  53. #token "\\\""        << zzmore(); >>
  54. #token "\\n"        << zzreplchar('\n'); zzmore(); >>
  55. #token "\\r"        << zzreplchar('\r'); zzmore(); >>
  56. #token "\\t"        << zzreplchar('\t'); zzmore(); >>
  57. #token "\\[1-9][0-9]*"
  58.                     << zzreplchar((char)strtol(zzbegexpr,NULL,10)); zzmore(); >>
  59. #token "\\0[0-7]*"    << zzreplchar((char)strtol(zzbegexpr,NULL,8)); zzmore(); >>
  60. #token "\\0x[0-9]+"    << zzreplchar((char)strtol(zzbegexpr,NULL,16)); zzmore(); >>
  61. #token "\\~[\n\r]"    << zzmore(); >>
  62. #token "[\n\r]"        << zzline++; zzmore(); /* print warning about \n in str */>>
  63. #token "~[\"\n\r\\]+"<< zzmore(); >>
  64.  
  65. #lexclass CHARACTERS
  66. #token CHARACTER    "'" << zzmode(START); >>
  67. #token "\\'"        << zzmore(); >>
  68. #token "\\n"        << zzreplchar('\n'); zzmore(); >>
  69. #token "\\r"        << zzreplchar('\r'); zzmore(); >>
  70. #token "\\t"        << zzreplchar('\t'); zzmore(); >>
  71. #token "\\[1-9][0-9]*"
  72.                     << zzreplchar((char)strtol(zzbegexpr,NULL,10)); zzmore(); >>
  73. #token "\\0[0-7]*"    << zzreplchar((char)strtol(zzbegexpr,NULL,8)); zzmore(); >>
  74. #token "\\0x[0-9]+"    << zzreplchar((char)strtol(zzbegexpr,NULL,16)); zzmore(); >>
  75. #token "\\~[\n\r]"    << zzmore(); >>
  76. #token "[\n\r]"        << zzline++; zzmore(); /* print warning about \n in str */>>
  77. #token "~[\'\n\r\\]"<< zzmore(); >>
  78.  
  79. #lexclass START
  80.  
  81. #token OCT_NUM "[0][0-7]*"
  82. #token L_OCT_NUM "[0][0-7]*[Ll]"
  83. #token INT_NUM "[1-9][0-9]*"
  84. #token L_INT_NUM "[1-9][0-9]*[Ll]"
  85. #token HEX_NUM "[0][Xx][0-9A-Fa-f]+"
  86. #token L_HEX_NUM "[0][Xx][0-9A-Fa-f]+[Ll]"
  87. #token FNUM "([1-9][0-9]*{.[0-9]*} | {[0]}.[0-9]+) {[Ee]{[\+\-]}[0-9]+}"
  88. #token PreInc "\+\+"
  89. #token PreDec "\-\-"
  90. #token LPAREN "\("
  91. #token LBRACK "\["
  92. #token SizeOf "sizeof"
  93.  
  94. globals!:    <<AST *base, *t; Sym *p;
  95.               zzs_scope(&Globals);>>
  96.  
  97.             (    <<;>>
  98.                 <<Params=NULL;>> decl[GLOBAL]
  99.             |    <<Params=NULL;>>
  100.                 <<base = #[BaseTypeQ,scNone,0,tInt,NULL];>>
  101.                 declarator[base]
  102.                 <<handleSymbol(scNone, $1.text, #1, NULL, GLOBAL);
  103.                   t = defineArgs(#1, &Params);
  104.                 >>
  105.                 func_def[t]
  106.                 <<english( #(#[SymQ,$1.text,#2], #1) );>>
  107.                 <<Proto($1.text, #1);
  108.                   ProtoBoth($1.text, #1);
  109.                   p = zzs_rmscope(&Params);
  110.                   pScope(p, "parameters\n");
  111.                 >>
  112.             )*
  113.  
  114.             <<p = zzs_rmscope(&Globals);
  115.               pScope(p, "globals\n");
  116.               ProtoVars(p);>>
  117.             "@"
  118.         ;
  119.  
  120. /* d e c l  --  recognize a declaration or definition.
  121.  *
  122.  * We handle typedefs in a bizarre way.  WORD's are converted
  123.  * to TypeName's inside the lexical action for token WORD.  So,
  124.  * because of the lookahead, we need to get a TypeName into
  125.  * the symbol table before the lookahead can get a reference
  126.  * to this. e.g. "typedef int I; I i;"  We actually add the typedef
  127.  * name to the symbol table when we see its definition in
  128.  * rule declaration and friends.  Aggregate tags are handled in a
  129.  * similar fashion by adding them to the symbol table as they
  130.  * are declared.
  131.  *
  132.  * functions definitions always have a FunctionQ node at the root
  133.  * of the declarator since anything in front would make a pointer to
  134.  * a function or whatever.  e.g. int *f(); --> () * int --> "function
  135.  * returning pointer to integer."  Or, int (*f)() --> * () int -->
  136.  * "pointer to function returning integer."  The first is a function
  137.  * symbol, the 2nd is a variable.
  138.  */
  139. decl![int level]
  140.         :    <<int sc=scNone, t=tInt, cv=cvNone, typ;
  141.               AST *base, *d, *init=NULL, *tr;
  142.               char *w;
  143.               Sym *n=NULL, *p;>>
  144.             (    (sclass[&sc] | typeq[&cv])+
  145.                 (    type[&t]        <<base = #[BaseTypeQ,cv,sc,t,$1.text];>>
  146.                 |    aggr[sc,cv]        <<base = #1;>>
  147.                 |    enum_def        <<base = #1;>>
  148.                 |                    <<base = #[BaseTypeQ,cv,sc,tInt,NULL];>>
  149.                 )
  150.             |    type[&t]            <<base = #[BaseTypeQ,cvNone,scNone,t,$1.text];>>
  151.             |    aggr[scNone,cvNone]    <<base = #1;>>
  152.             |    enum_def            <<base = #1;>>
  153.             )
  154.             (    declarator[base]    <<d=#1; w=$1.text;>>
  155.                 (    { <<init=NULL;>> "=" initialize <<init=#2;>> }
  156.                     <<if ( d->nodeType == FunctionQ ) {
  157.                         sc |= scExtern;
  158.                         bottom(d)->data.t.sc |= scExtern;
  159.                       }
  160.                       handleSymbol(sc, w, d, init, $level);>>
  161.                     (    <<english( #(#[SymQ,w,init], d) );>>
  162.                         ","
  163.                         declarator[base]
  164.                         { <<init=NULL;>> "=" initialize <<init=#2;>> }
  165.                         <<english( #(#[SymQ,$2.text,init], #2) );>>
  166.                         <<if ( #2->nodeType == FunctionQ ) {
  167.                             sc |= scExtern;
  168.                             bottom(#2)->data.t.sc |= scExtern;
  169.                           }
  170.                           handleSymbol(sc, $2.text, #2, init, $level);>>
  171.                     )*
  172.                     <<
  173.                     if ( base->data.t.type==tStruct ||
  174.                          base->data.t.type==tUnion ||
  175.                          base->data.t.type==tEnum )
  176.                     {
  177.                         if ( base->data.t.name != NULL )
  178.                         {
  179.                             p = zzs_get(base->data.t.name);
  180.                             if ( p!=NULL ) p->level = $level;
  181.                         }
  182.                     }
  183.                     >>
  184.                     ";"
  185.                 |    <<
  186.                         handleSymbol(sc, w, d, init, $level);
  187.                         tr = defineArgs(d, &Params);
  188.                     >>
  189.                     func_def[tr]
  190.                     <<english( #(#[SymQ,w,#1], d) );>>
  191.                     <<Proto(w, d);
  192.                       ProtoBoth(w, d);
  193.                       p = zzs_rmscope(&Params);
  194.                         pScope(p, "block\n");
  195.                     >>
  196.                 )
  197.             |    ";"
  198.                 <<english( base );>>
  199.                 <<if ( base->data.t.type==tStruct ||
  200.                        base->data.t.type==tUnion ||
  201.                        base->data.t.type==tEnum )
  202.                   {
  203.                     p = zzs_get(base->data.t.name);
  204.                     if ( p!=NULL ) p->level = $level;
  205.                   }
  206.                   else
  207.                     error("missing declarator");
  208.                 >>
  209.             )
  210.         ;
  211.  
  212. sclass![int *sc]
  213.         :    "auto"                <<*$sc |= scAuto;>>
  214.         |    "static"            <<*$sc |= scStatic;>>
  215.         |    "register"            <<*$sc |= scRegister;>>
  216.         |    "extern"            <<*$sc |= scExtern;>>
  217.         |    "typedef"            <<*$sc |= scTypedef;>>
  218.         ;
  219.  
  220. typeq![int *cv]
  221.         :    "const"                <<*$cv |= cvConst;>>
  222.         |    "volatile"            <<*$cv |= cvVolatile;>>
  223.         ;
  224.  
  225. type![int *t]
  226.         :    t1[t]                <<$type = $1;>>
  227.         ;
  228.  
  229. t1![int *type]
  230.         :    (    "unsigned"        <<*$type = tUnsigned;>>
  231.             |    "signed"        <<*$type = tSigned;>>
  232.             )
  233.             (    "char"            <<*$type |= tChar;>>
  234.             |    { "short"        <<*$type |= tShort;>>
  235.                 | "long"        <<*$type |= tLong;>>
  236.                 }
  237.                 { "int"            <<*$type |= tInt;>>
  238.                 }
  239.             )
  240.         |    (    "short"            <<*$type = tShort;>>
  241.                 { "int"         <<*$type |= tInt;>>
  242.                 }
  243.             |    "long"            <<*$type = tLong;>>
  244.                 { "int"            <<*$type |= tInt;>>
  245.                 | "float"        <<*$type |= tFloat;>>
  246.                 | "double"        <<*$type |= tDouble;>>
  247.                 }
  248.             )
  249.         |    "void"                <<*$type = tVoid;>>
  250.         |    "char"                <<*$type = tChar;>>
  251.         |    "int"                <<*$type = tInt;>>
  252.         |    "float"                <<*$type = tFloat;>>
  253.         |    "double"            <<*$type = tDouble;>>
  254.         |    TypeName            <<*$type = tTypeName; $t1 = $1;>>
  255.         ;
  256.  
  257. /* D e c l a r a t o r */
  258.  
  259. /*
  260.  * Build a declarator by appending the base to the bottom of the type-tree
  261.  * matched in dcltor1.  We pass the storage class to dcltor1 in case
  262.  * we have a typedef on our hands which needs to be added to the symbol
  263.  * table ASAP.
  264.  */
  265. declarator![AST *base]
  266.         :    dcltor1[bottom($base)] <<#(bottom(#1), $base);
  267.                                        #0 = (#1==NULL)?$base:#1;
  268.                                      $declarator = $1;>>
  269.         ;
  270.  
  271. /*
  272.  * Match *D1 or D2.  Build type-trees for PointerQ (pointer qualifier)
  273.  * via:
  274.  *
  275.  * #0 =     D1
  276.  *            |
  277.  *            v
  278.  *            *
  279.  *
  280.  * where D? is dcltor? in this grammar.
  281.  */
  282. dcltor1![AST *base]
  283.         :    <<AST *t; int cv=0;>>
  284.             "\*"
  285.             {    "const"            <<cv=cvConst;>>
  286.             |    "volatile"        <<cv=cvVolatile;>>
  287.             }                    <<t = #[PointerQ,cv];>>
  288.             dcltor1[$base]        <<#(bottom(#3), t); #0=(#3==NULL)?t:#3;
  289.                                   $dcltor1 = $3;>>
  290.         |    dcltor2[$base]        <<#0 = #1; $dcltor1 = $1;>>
  291.         ;
  292.  
  293. /*
  294.  * For WORD D3 we return the following
  295.  *
  296.  * $$ =        WORD recognized.
  297.  * #0 =      D3                    (array or func modifier)
  298.  *
  299.  * For ( D1 ) we return
  300.  *
  301.  * $$ =        WORD recognized in D1.
  302.  * #0 =        D1                    (put stuff in (..) above [] or ())
  303.  *            |
  304.  *            v
  305.  *            D3
  306.  *
  307.  * For instance, (*f)() yields
  308.  *
  309.  * $$ =        f
  310.  * #0 =        *                    (pointer to)
  311.  *            |
  312.  *            v
  313.  *           ( )                    (a function)
  314.  *
  315.  * If storage class is scTypedef, we need to add it to the symbol table.
  316.  */
  317. dcltor2![AST *base]                /* pass in storage class for typedefs */
  318.         :    <<AST *t; Sym *n;>>
  319.             WORD                <<if ( $base->data.t.sc&scTypedef )
  320.                                     addsym(TypeName,$1.text,0,NULL,NULL);
  321.                                 >>
  322.             dcltor3                <<#0 = #2; $dcltor2 = $1;>>
  323.         |    "\(" dcltor1[$base] "\)" <<$dcltor2 = $2;>> 
  324.             dcltor3                <<#(bottom(#2), #4); #0=(#2==NULL)?#4:#2;>>
  325.         ;
  326.  
  327. /*
  328.  * return #0 = [expr] or = [nodimension]
  329.  * or ( ) --> arg1 --> ... --> argn for a function
  330.  *
  331.  * multiple [1][2][3] yields
  332.  *
  333.  * #0 =       [1]                    (an 1-element array of)
  334.  *            |
  335.  *            v
  336.  *           [2]                    (2-element arrays of)
  337.  *            |
  338.  *            v
  339.  *           [3]                    (3-element arrays)
  340.  *            
  341.  */
  342. dcltor3!:    "\[" expr1 "\]" dcltor3    <<#0 = #( #[ArrayQ,#2], #4 );>>
  343.         |    "\[" "\]" dcltor3        <<#0 = #( #[ArrayQ,NULL], #3 );>>
  344.         |    "\(" args "\)"            <<#0 = #(NULL, #[FunctionQ], #2);>>
  345.         |                            <<#0 = NULL;>>
  346.         ;
  347.  
  348. /*
  349.  * match a list of arguments.
  350.  *
  351.  * The arguments are siblings of the FunctionQ node in the type
  352.  * tree.  e.g.
  353.  *
  354.  *    [FunctionQ]-->[arg1]--> ... -->[argn]
  355.  *                     |                 |
  356.  *                     v                 v
  357.  *                 [type1]          [type1]
  358.  */
  359. args!    :    <<AST *t;>>
  360.             arg                    <<t=#1;>>
  361.             (    "," arg            <<t = #(NULL, t, #2);>>
  362.             )*
  363.             {    "," "..."        <<t=#(NULL,t,#[BaseTypeQ,0,0,tEllipsis,NULL]);>>
  364.             }
  365.             <<#0 = t;>>
  366.         |
  367.         ;
  368.  
  369. arg!    :    typename            <<#0 = #1;>>
  370.         |    WORD                <<#0 = #[SymQ,$1.text,NULL];>>
  371.         ;
  372.  
  373. /*
  374.  * match a typename -- (used in type-casting and function prototypes).
  375.  * Type-trees look the same as those for decl.  But, a symbol is
  376.  * optional here because they can be used in argument lists.
  377.  */
  378. typename!:    <<int sc=0, cv, t=tInt; AST *base, *tr=NULL;>>
  379.             (    ("register" <<sc = scRegister;>> | typeq[&cv])+
  380.                 {    type[&t]    <<base = #[BaseTypeQ,cv,sc,t,$1.text];>>
  381.                 |    aggr[scNone,cv]    <<base = #1;>>
  382.                 }
  383.             |    type[&t]        <<base = #[BaseTypeQ,0,0,t,$1.text];>>
  384.             |    aggr[scNone,cvNone]    <<base = #1;>>
  385.             )
  386.             tdecl[base]            <<if ($2.text[0]!='\0') tr=#[SymQ,$2.text,NULL];
  387.                                   #0=#(tr, #2);>>
  388.         ;
  389.  
  390. /* A g g r e g a t e s */
  391.  
  392. /*
  393.  * match an enum definition; yield following tree:
  394.  *
  395.  * [BaseTypeQ] --> [elem1] --> ... --> [elemn] 
  396.  */
  397. enum_def!:    <<AST *base;>>
  398.             "enum" WORD            <<base=#[BaseTypeQ,0,0,tEnum,$2.text];>>
  399.             enum_lst            <<#0 = #(NULL, base, #3);>>
  400.         ;
  401.  
  402. /*
  403.  * match a list of enumeration elements.
  404.  *
  405.  * The symbols are siblings of each other:
  406.  *
  407.  * [elem1] --> ... --> [elemn] 
  408.  *
  409.  * If an element has an initialization, store a pointer to it in the
  410.  * AST node.
  411.  */
  412. enum_lst!:    <<AST *list, *init=NULL;>>
  413.             "\{"
  414.             WORD
  415.             {    "=" expr1        <<init = #2;>>
  416.             }                    <<list = #[SymQ,$2.text, init];>>
  417.             (    ","
  418.                 WORD
  419.                 {                <<init=NULL;>>
  420.                     "=" expr1    <<init=#2;>>
  421.                 }                <<list = #(NULL,list,#[SymQ,$2.text, init]);>>
  422.             )*
  423.             "\}"
  424.                                 <<#0 = list;>>
  425.         |                        <<#0 = NULL;>>
  426.         ;
  427.  
  428. /*
  429.  * Match a struct/union def.
  430.  * Return a tree like this:
  431.  * 
  432.  *    [BaseTypeQ]-->[fld1]--> ... -->[fldn]
  433.  *                     |                 |
  434.  *                     v                 v
  435.  *                 [type1]          [type1]
  436.  *
  437.  * BUG: Allows two structs to have same name
  438.  */
  439. aggr![int sc, int cv]
  440.         :    <<AST *tr, *base; int t; Sym *typ;>>
  441.             (    "struct"        <<t=tStruct;>>
  442.             |    "union"            <<t=tUnion;>>
  443.             )                    <<base = #[BaseTypeQ,$cv,$sc,t,NULL];>>
  444.             (    (    WORD        <<base->data.t.name = mystrdup($1.text);>>
  445.                 |    TypeName    <<base->data.t.name = mystrdup($1.text);>>
  446.                 )
  447.                 ( ag[base]        <<#0 = #(NULL, base, #1);
  448.                                   addsym(AggrTag, base->data.t.name,
  449.                                          0, base, NULL);
  450.                                 >>
  451.                 |                <<#0 = base;>>
  452.                 )
  453.             |    ag[base]        <<#0 = #(NULL, base, #1);>>
  454.             )
  455.         ;
  456.  
  457. /*
  458.  * match a field list for a struct/union
  459.  *
  460.  * The fields are siblings of each other:
  461.  *
  462.  *  [fld1] --> ... --> [fldn] 
  463.  *      |                     |
  464.  *      v                     v
  465.  * [type1]              [type1]
  466.  *
  467.  */
  468. ag![AST *base]
  469.         :    <<AST *t=NULL;>>
  470.             "\{" fdef[$base]    <<#0=t=#2;>>
  471.             (    fdef[$base]        <<#(NULL, t, #1); t = #1;>>
  472.             )*
  473.             "\}"
  474.         ;
  475.  
  476. /*
  477.  * Match one field definition; make the following tree
  478.  *
  479.  * [FieldQ]
  480.  *       |
  481.  *       v
  482.  *  [type1]
  483.  */
  484. fdef![AST *base]
  485.         :    <<int t=tInt; AST *f, *g;>>
  486.             (    type[&t]        <<base = #[BaseTypeQ,0,0,t,$1.text];>>
  487.             |    aggr[scNone,cvNone]    <<base = #1;>>
  488.             )
  489.             field[$base]        <<f = #(#[FieldQ,$2.text], #2);>>
  490.             (    "," field[$base]<<g = #(#[FieldQ,$2.text], #2);
  491.                                   f = #(NULL, f, g);>>
  492.             )*
  493.             ";"
  494.             <<#0 = f;>>
  495.         ;
  496.  
  497. /* bitfields are recognized, but not handled 'cause not too many people
  498.  * use them
  499.  */
  500. field![AST *base]
  501.         :    declarator[$base] { ":" expr1 } <<#0=#1; $field = $1;>>
  502.         |    ":" expr1
  503.         ;
  504.  
  505. /* T y p e  N a m e */
  506.  
  507. tdecl![AST *base]
  508.         :    tdecl1                <<#(bottom(#1), $base);
  509.                                   #0 = (#1==NULL)?$base:#1; $tdecl=$1;>>
  510.         ;
  511.  
  512. tdecl1! :    <<AST *t; int cv=0;>>
  513.             "\*"
  514.             {    "const"            <<cv=cvConst;>>
  515.             |    "volatile"        <<cv=cvVolatile;>>
  516.             }                    <<t = #[PointerQ,cv];>>
  517.             tdecl1                <<#(bottom(#3), t); #0=(#3==NULL)?t:#3;
  518.                                   $tdecl1 = $3;>>
  519.         |    tdecl2                <<#0 = #1; $tdecl1 = $1;>>
  520.         ;
  521.  
  522. tdecl2!    :    <<AST *t=NULL; $tdecl2.text[0] = '\0';>>
  523.             "\(" tdecl1 "\)"    <<$tdecl2 = $2;>>
  524.             tdecl3                <<#(bottom(#2), #4); #0=(#2==NULL)?#4:#2;>>
  525.         |    WORD tdecl3            <<$tdecl2 = $1; #0 = #2;>>
  526.         |    tdecl3                <<#0 = #1;>>
  527.         ;
  528.  
  529. tdecl3!    :    "\[" expr1 "\]" tdecl3<<#0 = #( #[ArrayQ,#2], #4 );>>
  530.         |    "\[" "\]"     tdecl3<<#0 = #( #[ArrayQ,NULL], #3 );>>
  531.         |    "\(" args "\)"        <<#0 = #( NULL, #[FunctionQ], #2 );>>
  532.         |
  533.         ;
  534.  
  535.  
  536. /* I n i t  e x p r e s s i o n s */
  537.  
  538.  
  539. initialize
  540.         :    init2
  541.         |    expr0
  542.         ;
  543.  
  544. /* Build an initialization expression-tree of the form:
  545.  *
  546.  * Single-dimensioned array or structure:
  547.  *
  548.  *    "{"
  549.  *     |
  550.  *     v
  551.  *    [exp1] --> ... --> [expn]
  552.  *
  553.  * Nested structure or multi-dim array:
  554.  *
  555.  *    "{"
  556.  *     |
  557.  *     v
  558.  *    "{" --> ... --> "{"
  559.  *     |                ...
  560.  *     v                ...
  561.  *    [exp1] --> ... --> [expn]
  562.  */
  563. init2    :    "\{"^ init3 ( ","! init3 )* {","!} "\}"!
  564.         ;
  565.  
  566. init3    :    init2
  567.         |    expr1
  568.         ;
  569.